package cn.tedu.csmall.passport.service.impl;

import cn.tedu.csmall.passport.ex.ServiceException;
import cn.tedu.csmall.passport.mapper.AdminMapper;
import cn.tedu.csmall.passport.pojo.dto.AdminAddNewDTO;
import cn.tedu.csmall.passport.pojo.dto.AdminLoginDTO;
import cn.tedu.csmall.passport.pojo.entity.Admin;
import cn.tedu.csmall.passport.pojo.vo.AdminListItemVO;
import cn.tedu.csmall.passport.service.IAdminService;
import cn.tedu.csmall.passport.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;

@Slf4j
@Service
public class AdminServiceImpl implements IAdminService {
    @Autowired
   private PasswordEncoder passwordEncoder;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Override
    public void addNew(AdminAddNewDTO adminAddNewDTO) {
        log.debug("开始处理增加管理员的业务,参数:{}",adminAddNewDTO);

        String username = adminAddNewDTO.getUsername();
        int count = adminMapper.countByUsername(username);
        if (count>0){
            String message ="添加管理员失败，用户名【" + username + "】已经被占用！";
            log.error(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT,message);
        }

        Admin admin = new Admin();
        BeanUtils.copyProperties(adminAddNewDTO,admin);
        admin.setLoginCount(0);
        admin.setLastLoginIp(null);
        admin.setGmtLastLogin(null);
        // TODO: 2022/7/12 将原密码从Admin对象中取出,加密后再存入到Admin对象中
        String rawPassword = admin.getPassword();
        String encodedPassword=passwordEncoder.encode(rawPassword);
        admin.setPassword(encodedPassword);

        log.debug("数据写入数据库:{}",admin);
        int rows= adminMapper.insert(admin);
        if (rows != 1) {
            String message = "添加管理员失败，服务器忙，请稍后再次尝试！";
            log.error(message);
            throw new ServiceException(ServiceCode.ERR_INSERT,message);
        }
    }

    @Override
    public String login(AdminLoginDTO adminLoginDTO) {
        log.debug("开始处理管理员登陆的业务.,参数:{}",adminLoginDTO);
        Authentication authentication
                =new UsernamePasswordAuthenticationToken(
                        adminLoginDTO.getUsername(),adminLoginDTO.getPassword());
        Authentication loginResult = authenticationManager.authenticate(authentication);

        log.debug("登录成功!认证方法返回:{} >>> {}",loginResult.getClass().getName(),loginResult);
        log.debug("尝试获取Principal:{} >>> {}",loginResult.getPrincipal().getClass().getName(),loginResult);
        User user = (User) loginResult.getPrincipal();
        String username = user.getUsername();
        log.debug("登陆成功的用户名:{}",username);

        Collection<GrantedAuthority> authorities = user.getAuthorities();
        log.debug("登陆成功的权限:{}",authorities);
        String authoritiesString = JSON.toJSONString(authorities);
        log.debug("将权限转化为JSON:{}",authoritiesString);

        Map<String,Object> claims = new HashMap<>();
        claims.put("username",user.getUsername());
        claims.put("authorities",authoritiesString);

        Date expiration = new Date(System.currentTimeMillis()+ 3 * 24 * 60 * 60 * 1000 );
        String jwt = Jwts.builder()
                .setHeaderParam("typ","jwt")
                .setHeaderParam("alg","HS256")
                .setClaims(claims)
                .setExpiration(expiration)
                .signWith(SignatureAlgorithm.HS256,"sdfdsgsdgdsgdsgdsfsdfsdag32wrw")
                .compact();
        log.debug("生成jwt数据：{}",jwt);

        return jwt;
    }

    @Override
    public List<AdminListItemVO> list() {
        log.debug("开始查询处理管理员列表");
        return adminMapper.list();
    }
}
